09 - Output Devices
Controlling a Motor
After having done the electronics design and production of the PCB for my final project last week, this week it is time to add the external devices to it and program the microcontroller to control it. More specifically, this week so far only concerns output devices. Input devices will be the topic after the next one.
This weeks's assignment were:
- Group Assignment
- Measure the power consumption of an output device
- Individual Assignment
- Add an output device to a microcontroller board you've designed and program it to do something
Group Assignment
For the group assignment, our task was to measure the power consumption of an output device. As all of us measured the power consumption of the output devices we were using for the individual assignment, we decided to document the findings on our individual assignment's page only. For me, the output devices were a NEMA 17 stepper motor and an LED strip. For the details on the wiring and the programming of the PCB for control, please refer to the documentation of the individual assignment below.
The power can be easily measured by using a bench power supply. For example for the motor, I connected the bench power supply to the motor driver and set it to the maximum voltage of 21.18 V. The current however was load depending meaning the motor and the motor driver can take as much current as needed. The power consumption can then be then calculated by multiplying the voltage with the load that can be read from the display of the power supply during controlling the motor.
In my case, while the motor was rotating, the power supply showed a voltage of the specified 21.18 V and a load-dependent current of only 0.183 A. With power equals voltage in volts times current in amperes, the power consumption of the motor and the motor driver amounts to about 3.88 W. Also, decreasing the voltage resulted in a slightly higher current such that the power stayed constant.
I was actually surprised that the current is that low as the datasheet of the motor says that the motor needs 1.5 A per phase. However, if the torque of the motor is required to be higher, the load and by this the current might increase.
For the LED strip that I bought, namely this one, I used a different bench power supply that was able to supply voltages beyond 21.18 V as it operates with 24 V. While it was switched on without any pulse width modulation (PWM), I took a photo of the power supply. The voltage was at 24.4 V and the load dependent current at 0.63 A equaling a power of 15.372 W. This is about what I expected as the vendor of the LED strip specifies the power consumption as 10.8 W/m. With a length of 1.5 m, this would sum up to 16.2 W.
Individual Assignment
For my final project, I will have two output devices that I need to control, namely a motor with a motor driver, and an LED strip with a MOSFET. The details of these components are shown in last's week documentation. However, the LED strip has not yet arrived and therefore, I will be starting with the motor. In case you have already a second section with content about how to control the brightness of an LED strip with a MOSFET, then the LED strip has already arrived so I was able to include it in my assignment.
Controlling a Motor
For last week's assignment, I already picked the electrical components necessary for controlling a motor. The motor itself is a NEMA 17 stepper motor which is driven by an A4988 motor driver. Firstly, I set up the circuit necessary for using the motor driver and the motor and then continued with programming. Here, I started with only wanting to make the motor move and then proceeded with controlling the speed of the motor.
Circuit Diagram of th Setup
For setting up the electrical circuit, I used the minimal wiring diagram that the manufacturer of the motor driver supplies. It includes a logical power supply from the microcontroller to the motor driver with 3 V to 5.5 V, an external power supply between 8 V and 35 V to power the motor, four wires to the motor from the motor driver, a connection of the RESET and SLEEP pin of the motor driver and a connection from the microcontroller to the STEP and DIR pin of the motor driver.
To make all of these connections, I used a bread board and jumper cables. I started by mounting the motor driver on it such that both sides of it are on either side of the bread board. Then, I used many different jumper wired to make all the necessary connections. I started by supplying the logical power to the driver by connecting the a power and ground pin with a red and black cable to the PCB. For this, I used the PCB that I fabricated during the electronics production week.
Then, I connected the pins I want to use for controlling at the microcontroller with the according pins on the motor driver. These are the DIR (direction, yellow jumper), STEP (orange jumper) and ENABLE pin (purple jumper). Additionally, I connected the RESET and SLEEP pin with a red wire.
Lastly, I attached the four wires of the motor and the motor power supply to the motor driver. For the latter, I used a large DC bench power supply from the lab equipment. For this, I used the maximum voltage of 21.18 V, which was the closest to 24 V which I will be using for my final project to share a power supply with the LED strip. The current however was load dependent and I did not need to specify it.
Making the Motor Move
Making the motor move was actually relatively easy. After the circuit was set up, I only had some programming left which I did in the Arduino IDE. Please refer to the documentation of the embedded programming week for how to use the Arduino IDE with the PCB I fabricated in the electronics production week.
Programming the Seeeduino on the PCB only concerned the three output pins, DIR for direction, STEP for a step and ENABLE for enabling. The last pin is active low which is shown in the minimal wiring diagram above with the horizontal bar on top of it. Hence, this pin had to be set to low.
The direction pin is also relatively straight forward. Depending on the input to this pin, so either LOW or HIGH, the motor rotates either clockwise or counterclockwise. The direction can therefore simply be switched by setting the direction pin to HIGH from LOW or vice versa.
The last pin to control is the STEP pin. A single step is performed for one pulse, i.e. if the pin switches from a LOW state to a HIGH state and a LOW state again in a fracture of a second, typically a couple hundreds of microseconds.
The code below shows what I have programmed. After the setup with defining certain pins as outputs and enabling the motor driver, the code sets a particular direction. For this direction, 2000 steps are performed by generating 2000 pulses. This is repeated for the other direction after a pause of a second.
// Define pin numbers
const int dirPin = 1; // direction
const int stepPin = 2; // step
const int enaPin = 3; // enable
void setup() {
// Define all pins at output
pinMode(stepPin,OUTPUT);
pinMode(dirPin,OUTPUT);
pinMode(enaPin,OUTPUT);
// Enable the motor driver
digitalWrite(enaPin,LOW);
}
void loop() {
digitalWrite(dirPin,HIGH); // Set the rotation to one particular direction
// Perform 2000 steps
for(int x = 0; x < 2000; x++) {
// Generate a pulse
digitalWrite(stepPin,HIGH);
delayMicroseconds(700);
digitalWrite(stepPin,LOW);
delayMicroseconds(700);
}
delay(1000); // Wait for a second
digitalWrite(dirPin,LOW); // Set the rotation to the other direction
// Perform 2000 steps
for(int x = 0; x < 2000; x++) {
// Generate a pulse
digitalWrite(stepPin,HIGH);
delayMicroseconds(700);
digitalWrite(stepPin,LOW);
delayMicroseconds(700);
}
delay(1000); // Wait for a second
}
As I had expected, this is also exactly what the motor did. It was rotating, paused for a second and then rotated in the other direction and waited for another second until repeating these steps. In fact, the motor actually performed exactly ten rotations. This is due to the stepping angle. A single step is equivalent to 1.8° such that 200 steps are needed for a complete rotation. The 2000 steps that I programmed therefore result in ten full rotations.
Motor Rotates in Both Directions
Controlling the Speed
In order to change the speed of the microcontroller, the pulse frequency can be changed. This can be done by adjusting the
length of the HIGH and LOW phase of a pulse. In the programmed code above, the length is defined with the
command delayMicroseconds(700);
to be 700 microseconds long. In order to make the motor move faster,
the pulse must be faster and the duration shorter. Vice versa, for a slower rotation speed, the pulse and the
duration must be longer.
I programmed the microcontroller with the following code to firstly spin fast, then at an intermediate speed and lastly at a low speed.
// Define pin numbers
const int dirPin = 1; // direction
const int stepPin = 2; // step
const int enaPin = 3; // enable
void setup() {
// Define all pins at output
pinMode(stepPin, OUTPUT);
pinMode(dirPin, OUTPUT);
pinMode(enaPin, OUTPUT);
// Enable the motor driver
digitalWrite(enaPin, LOW);
// Set the rotation to one particular direction
digitalWrite(dirPin, HIGH);
}
void loop() {
// Perform 1000 steps with few us delay -> fast
for (int x = 0; x < 1000; x++) {
// Generate a pulse
digitalWrite(stepPin, HIGH);
delayMicroseconds(400);
digitalWrite(stepPin, LOW);
delayMicroseconds(400);
}
delay(1000); // Wait for a second
// Perform 1000 steps with intermediate us delay -> medium
for (int x = 0; x < 1000; x++) {
// Generate a pulse
digitalWrite(stepPin, HIGH);
delayMicroseconds(800);
digitalWrite(stepPin, LOW);
delayMicroseconds(800);
}
delay(1000); // Wait for a second
// Perform 1000 steps with many us delay -> slow
for (int x = 0; x < 1000; x++) {
// Generate a pulse
digitalWrite(stepPin, HIGH);
delayMicroseconds(1200);
digitalWrite(stepPin, LOW);
delayMicroseconds(1200);
}
delay(1000); // Wait for a second
}
As expected, I saw the motor firstly spin fast, then at an intermediate speed and lastly at a lower speed. Please note that the motor performs 1000 steps at different speeds. As the stepper motor resolution is 1.8° meaning that it takes 200 steps for a full rotation of 360°, the motor performs five full rotations per speed.
Motor Rotates With Different Speeds
Decreasing the Speed with Delays
After this test, I was curious what the lower speed limit was. For this, I used this script:
// Define pin numbers
const int dirPin = 1; // direction
const int stepPin = 2; // step
const int enaPin = 3; // enable
const int delay_us = 2100; //duration of HIGH and LOW phase: min. 320; max. 2000
void setup() {
// Define all pins at output
pinMode(stepPin, OUTPUT);
pinMode(dirPin, OUTPUT);
pinMode(enaPin, OUTPUT);
// Enable the motor driver
digitalWrite(enaPin, LOW);
// Set the rotation to one particular direction
digitalWrite(dirPin, HIGH);
}
void loop() {
// Perform 1000 steps
for (int x = 0; x < 400; x++) {
// Generate a pulse
digitalWrite(stepPin, HIGH);
delayMicroseconds(delay_us);
digitalWrite(stepPin, LOW);
delayMicroseconds(delay_us);
}
delay(1000); // Wait for a second
}
This script lets the motor spin as previously. However, the delays of microseconds and thus durations
of the HIGH and LOW phases of a pulse were defined by a variable called delay_us
. I let this
script run several times with different values. Here, I found out that the maximum of the variable is 2000 and
the minimum about 320. This means, one step is performed in 4000 and 640 microseconds respectively. As it takes
200 steps per round, this is equivalent to a speed of about 0.8 and 0.128 seconds per round.
However, this process rather finds out what the maximum speed is as this determines the minimum amount of microseconds between two HIGH phases of a pulse. However, a much lower speed can be achieved by increasing the duration of the LOW phase. This can be done for example with the code below.
// Define pin numbers
const int dirPin = 1; // direction
const int stepPin = 2; // step
const int enaPin = 3; // enable
void setup() {
// Define all pins at output
pinMode(stepPin, OUTPUT);
pinMode(dirPin, OUTPUT);
pinMode(enaPin, OUTPUT);
// Enable the motor driver
digitalWrite(enaPin, LOW);
// Set the rotation to one particular direction
digitalWrite(dirPin, HIGH);
}
void loop() {
// Perform 1000 steps
for (int x = 0; x < 1000; x++) {
// Generate a pulse
digitalWrite(stepPin, HIGH);
delayMicroseconds(600); // The HIGH phase of a pulse cannot be so long
digitalWrite(stepPin, LOW);
delayMicroseconds(25000); // A hugh delay for lower speed in the LOW phase
}
delay(1000); // Wait for a second
}
This code works similar to the previous codes. However, the duration of the LOW phase is greatly increased. This allows for a much lower speed. As the total duration amounts to 25600 microseconds per pulse and thus per step, this amounts to about 5.12 seconds per round. This is how the slow rotation looks like:
Motor Rotates With Slow Speed
Decreasing the Speed with Microstepping
Another way of decreasing the speed is by decreasing the step size by so-called microstepping. A single step for this motor is defined as 1.8° such that 200 steps are needed for a full round. However, the motor does not need to make a full step. Depending on the input to the motor driver at the MS1, MS2 and MS3 pins, the step size can be decreased up to one 16th of a full step. The following table shows the the states of the tree pins and the according microstep resolution. This table was adapted from this website.
MS1 | MS2 | MS3 | Microstep Resolution |
---|---|---|---|
LOW | LOW | LOW | Full Step |
HIGH | LOW | LOW | Half Step |
LOW | HIGH | LOW | Quarter Step |
HIGH | HIGH | LOW | Eighth Step |
HIGH | HIGH | HIGH | Sixteenth Step |
In this case, I connected the MS1, MS2 and MS3 pin to VCC to pull them HIGH. With this, I decreased the speed significantly even though the same initial script was running which I showed here. However, now, a single pulse is equal to one 16th of a step. Therefore, 3200 pulses are needed for a full rotation. Hence, the programmed 2000 pulses are equal to 0.625 rounds. This is how the motor turned:
Motor Rotates Slowely Due to Microstepping
In contrast to the previous method of decreasing the speed, microstepping results in a much smoother rotation. This can not only be sensed by touching the shaft but also visually perceptible due to some small movements of the motor and audibly due to the sounds of the movements on the table.
Controlling a Motor with my Final Project Board
In addition to the board that I made during the electronics production week, I also used the board I will be using for my final project, namely the one I designed and made in the electronics design week.
To program the board, I again made used of a programmer board. I connected my board to the programmer board via three jumper wires, one for VCC, one for ground and the last one for UPDI. Then, I configured the Arduino IDE for the microcontroller, namely the ATtiny1614. Lastly, I uploaded the Arduino sketch to make a motor rotate back and forth shown in this section. In only changed the pin definitions according to this documentation to
const int dirPin = 1; // direction
const int stepPin = 2; // step
const int enaPin = 3; // enable
for correctly addressing the desired pins. The details of the setup for programming are explained here.
Lastly, I inserted the motor driver into the female pins in the according orientation, attached the four wires of the motor to the pins next to the motor driver and connected a bench power supply to the according screw terminals for the power supply.
Motor Rotates Using the Final Project Board
As you can see in the video, the motor was spinning back and forth as achieved with the other board (see here).
Controlling an LED Strip with a MOSFET
It took a while but the LED strip has finally arrived, even on time to complete the assignment in the output devices week. Therefore, I started right away when the LED strip arrived. Last week for electronics design I already explored the theory about how to control switching an LED strip on and off and dim it by using a MOSFET. Based on this, I have connected the MOSFET and LED to a power supply and the microcontroller. Then, I programmed the microcontroller to do pulse width modulation (PWM).
Circuit Diagram of the Setup
For wiring up a MOSFET and the LED strip, I started with the documentation of last week with the topic electronics design. However, I did not use the board that I made because not all components had arrived yet so I was not able to finish and use it. Hence, I used the PCB that I made in the electronics production week and a breadboard.
The easiest way to mount a MOSFET to a breadboard is by using a through-hole-technology (THT) MOSFET. Luckily, we had this MOSFET in the lab as well, which has a threshold voltage of 2 V and can channel 55 V and 47 A from drain to source. It looks similar to the one shown in the image. From left to right, the pins are connected to the gate (G), drain (D) and source (S).
Next, I tried to resemble the wiring diagram which is shown in the image. I was reading about how MOSFETs work on this website when I found the image. I also used it to design the schematics of the PCB from last week in electronics design.
For wiring the MOSFET, I started with the two resistors, the 10 kiloohms pull-down resistor and the 1000 ohms gate resistor.I explained their purpose in last week's documentation as well. Then, I connected the PCB to it for which I used jumper cables, i.e. a purple jumper going to the gate resistor and a black one connecting the ground of the PCB to the ground line of the breadboard.
Then, I connected the source to the ground line of the breadboard. The drain pin, i.e. the middle pin, was connected to the minus side of the LED strip with a black jumper cable. The plus side of the LED strip and the ground line of the breadboard, i.e. the source or right pin of the MOSFET, I furthermore connected to the plus and minus voltage of a bench power supply, respectively. For this, I set the output voltage to 24 V whereas the output current was load dependent.
The image below shows how the complete wiring looks like. The two rapid wire clamps in the top left lead to the bench power supply and the coil in the bottom right corner is the coil of the LED strip.
Controlling the MOSFET with PWM
After being done with the wiring, I tried to program the microcontroller to control the MOSFET. As presented in the
global lecture on output devices, pulse width modulation (PWM) is achieved with the function analogWrite()
in the Arduino IDE. However, I did not know exactly how to do it. Therefore, I looked online and found
this forum. Here, I simply inserted the code
from this post. I added some comments and
changed the pin to the required pin. This is how the complete code looked like:
// Define pin of microcontroller leading to the gate of the MOSFET
int mosfet_pin = D1;
void setup() {
// Declare pin as output
pinMode(mosfet_pin, OUTPUT);
}
void loop() {
// Increase the duty cycle and by this brightness
for (int val = 0; val <= 100; val++) {
// PWM: Set the duty cycle to val/255
analogWrite(mosfet_pin, val);
delay(10); // Wait
}
// Decrease the duty cycle and by this brightness
for (int val = 100; val >= 0; val--) {
// PWM: Set the duty cycle to val/255
analogWrite(mosfet_pin, val);
delay(10); // Wait
}
}
This code worked really well. The microcontroller firstly increased the brightness of the LED strip and consecutively decreased it, repetitively. This is how it looks:
Coil of LED Strip Increases and Decreased the Brightness through PWM and a MOSFET
Theoretically, the brightness can be increased even further as the analogWrite()
function is on a scale from zero to
255. In the code above, the maximum value that was used is 100 which equals a duty cycle of about 40%.
Controlling the LED Strip with my Final Project Board
As for rotating the motor, I also used the board I made in the electronics design week for controlling the brightness of an LED strip with a MOSFET and PWM.
I connected the board the a programmer board as explained in and setup up the Arduino IDE for the ATtiny1614 microcontroller as described in this section. Then, I uploaded the script from above, namely this one. I only had to change the pin definition to
int mosfet_pin = 0;
for correctly addressing the desired pin. Lastly, I attached the LED strip and a bench power supply at the according screw terminal. As soon as I powered the LED with 24 V, the LED turned on and then repetitively increased and decreased the brightness.
Increasing and Decreasing the Brigthness with the Final Project Board
Source Code for Download
- Move Motor (.ino): Arduino sketch to make a motor move back and forth
- Motor Different Speeds (.ino): Arduino sketch to rotate the motor move at different speeds
- Motor Speed Range (.ino): Arduino sketch for determining the speed range by the pulse duration
- Motor Slow Speed (.ino): Arduino sketch to decrease the motor's speed
- PWM LED Brightness (.ino): Arduino sketch for dimming the LED's brightness via a MOSFET with PWM